#include <QApplication>
#include <boost/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/noncopyable.hpp>
#include <boost/ref.hpp>
#include <string>
#include <iostream>
using namespace std;

template <typename T>
class basic_atom: boost::noncopyable
{
public:
    typedef boost::mutex mutex_t;

    basic_atom(T x=T()) : n(x) {}
    T operator ++()
    {
        mutex_t::scoped_lock lock(mu);
        return ++n;
    }
    operator T() {return n;}
private:
    T n;
    mutex_t mu;
};

boost::mutex io_mu;

typedef basic_atom<int> atom_int;

void printing(atom_int &x, const string &str)
{
    for (int i = 0; i < 5; ++i) {
        {
            boost::mutex::scoped_lock lock(io_mu);
            cout << str << ++x << endl;
        }
        boost::this_thread::sleep(boost::posix_time::seconds(1));
    }
}

void to_interrupt(atom_int &x, const string &str)
try {
    for (int i = 0; i < 5; ++i) {
        {
            boost::mutex::scoped_lock lock(io_mu);
            cout << str << ++x << endl;
        }
        boost::this_thread::sleep(boost::posix_time::seconds(1));
    }
} catch (boost::thread_interrupted &) {
    cout << "thread_interrupted" << endl;
}

int main(int , char *[])
{
    atom_int x;
    boost::thread t(to_interrupt, boost::ref(x), "interrupt");
    boost::this_thread::sleep(boost::posix_time::seconds(2));
    t.interrupt();
    t.join();
    boost::thread t1(printing, boost::ref(x), "hello");
    boost::thread t2(printing, boost::ref(x), "boost");
    boost::this_thread::sleep(boost::posix_time::seconds(2));
    t1.timed_join(boost::posix_time::seconds(1));
    t2.join();
}
